from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin, CreateModelMixin, UpdateModelMixin
from rest_framework.response import Response
from apps.minapp import models
from rest_framework import serializers
from time import strftime
from random import Random
from django_filters.rest_framework import FilterSet, ChoiceFilter, DjangoFilterBackend
from rest_framework.pagination import PageNumberPagination, CursorPagination
import django.utils.timezone as timezone
import datetime, time
from django.db.models import Sum, F
from django.db import models as dbmodel
from apps.minapp.views.auction import getaccesstoken
import requests
from django_celery_results.models import TaskResult
from eatfun_backend import settings
from rest_framework.views import APIView


class OrderGoodsSerializer(serializers.ModelSerializer):
    name = serializers.SerializerMethodField()
    coversrc = serializers.SerializerMethodField()
    price = serializers.SerializerMethodField()
    description = serializers.SerializerMethodField()

    @staticmethod
    def get_name(obj):
        return obj.detail.cover.name

    @staticmethod
    def get_coversrc(obj):
        return str(obj.detail.cover.src)

    @staticmethod
    def get_price(obj):
        return obj.detail.cover.price

    @staticmethod
    def get_description(obj):
        return obj.detail.cover.description

    class Meta:
        model = models.OrderGoods
        fields = "__all__"


class OrderDetailSerializer(serializers.ModelSerializer):
    ordergoods = OrderGoodsSerializer(many=True)
    created_time = serializers.SerializerMethodField()
    pay_time = serializers.SerializerMethodField()
    shopname = serializers.SerializerMethodField()
    shopid = serializers.SerializerMethodField()

    @staticmethod
    def get_created_time(obj):
        return str(obj.created_time)[0:19]

    @staticmethod
    def get_pay_time(obj):
        return str(obj.created_time)[0:19]

    @staticmethod
    def get_shopname(obj):
        return obj.shop.title

    @staticmethod
    def get_shopid(obj):
        return obj.shop.id

    class Meta:
        model = models.OrderInfo
        fields = "__all__"


class OrderCoverSerializer(serializers.ModelSerializer):
    coversrc = serializers.SerializerMethodField()
    description = serializers.SerializerMethodField()
    name = serializers.SerializerMethodField()

    class Meta:
        model = models.OrderGoods
        fields = ['coversrc', 'description', 'num', 'name', 'id']

    @staticmethod
    def get_coversrc(obj):
        return str(obj.detail.cover.src)

    @staticmethod
    def get_description(obj):
        return obj.detail.cover.description

    @staticmethod
    def get_name(obj):
        return obj.detail.cover.name


class OrderListSerializer(serializers.ModelSerializer):
    ordergoods = OrderCoverSerializer(many=True)
    shopname = serializers.SerializerMethodField()
    shopid = serializers.SerializerMethodField()

    class Meta:
        model = models.OrderInfo
        fields = ['ordergoods', 'status', 'id', 'total_amount', 'shopname', 'shopid']

    @staticmethod
    def get_shopname(obj):
        return obj.shop.title

    @staticmethod
    def get_shopid(obj):
        return obj.shop.id


class OrderSerializer(serializers.ModelSerializer):
    user_id = serializers.HiddenField(
        default=serializers.CurrentUserDefault()
    )

    # 订单的某些信息是不能自己修改的
    status = serializers.CharField(read_only=True)
    order_sn = serializers.CharField(read_only=True)
    create_time = serializers.DateTimeField(read_only=True)
    pay_time = serializers.DateTimeField(read_only=True)

    def generate_order_sn(self):
        # 当前时间+userid+随机数
        random_ins = Random()
        order_sn = "{time_str}{userid}{ranstr}".format(time_str=strftime("%Y%m%d%H%M%S"),
                                                       userid=self.context['request'].user.id,
                                                       ranstr=random_ins.randint(10, 99))
        return order_sn

    # 对订单号进行生成
    def validate(self, attrs):
        attrs["order_sn"] = self.generate_order_sn()
        return attrs

    class Meta:
        model = models.OrderInfo
        fields = "__all__"


class OrderFilter(FilterSet):
    ORDER_STATUS_CHOICES = (
        (1, "待支付"),
        (2, "待接单"),
        (3, "制作中"),
        (4, "待取餐"),
        (5, "已完成"),
        (6, "已取消"),
    )
    status = ChoiceFilter(choices=ORDER_STATUS_CHOICES)

    class Meta:
        model = models.OrderInfo
        fields = ['status']


class OrderPagnation(CursorPagination):
    ordering = '-id'
    page_size = 15


# 用户———订单视图
class OrderView(RetrieveModelMixin, ListModelMixin, UpdateModelMixin, CreateModelMixin, GenericViewSet):
    queryset = models.OrderInfo.objects.all()
    serializer_class = OrderSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_class = OrderFilter
    pagination_class = OrderPagnation

    def get_queryset(self):
        return models.OrderInfo.objects.filter(user_id=self.request.user).order_by(
            '-pay_time')

    def get_serializer_class(self):
        if self.action == "list":
            return OrderListSerializer
        elif self.action == "retrieve":
            return OrderDetailSerializer
        return OrderSerializer

    # def retrieve(self, request, *args, **kwargs):
    #     instance = self.get_object()
    #     print(instance.ordergoods)
    #     serializer = self.get_serializer(instance)
    #     ordergoods = self.orderhandle(instance.ordergoods)
    #     print(ordergoods)
    #     res = serializer.data
    #     res.update({'ordergoods': ordergoods})
    #     return Response(res)

    def generate_order_sn(self):
        # 当前时间+userid+随机数
        random_ins = Random()
        order_sn = "{time_str}{userid}{ranstr}".format(time_str=strftime("%Y%m%d%H%M%S"),
                                                       userid=self.request.user.id,
                                                       ranstr=random_ins.randint(10, 99))
        return order_sn

    # 用户创建订单
    def create(self, request, *arsg, **kwargs):
        print(self.request.user)
        print(self.request.data)
        remarks = self.request.data['remarks']  # 用户的备注
        pay = self.request.data['pay']
        if pay:
            status = 2
            pay_time = timezone.now()
        else:
            status = 1
            pay_time = None
        shop_carts = models.ShoppingCart.objects.filter(user=self.request.user, checked=True, deleted=False)
        order = {}
        shops = set()
        for shop_cart in shop_carts:
            shop_id = shop_cart.goods.detail.shop_id
            if shop_id not in shops:
                shops.add(shop_id)
                torder = models.OrderInfo()
                torder.order_sn = self.generate_order_sn()
                torder.user_id = self.request.user
                torder.status = status
                torder.shop_id = shop_id
                torder.pay_time = pay_time
                queryset = models.ShoppingCart.objects.filter(user_id=self.request.user.id, checked=True, deleted=False,
                                                              goods__detail__shop_id=shop_id)
                total_amount = queryset.aggregate(
                    sum=Sum(F('goods__price') * F('num'),
                            output_field=dbmodel.DecimalField(decimal_places=2, max_digits=6)))[
                    'sum']
                print(total_amount)
                total_count = queryset.aggregate(sum=Sum('num'))['sum']
                torder.total_count = total_count
                torder.total_amount = total_amount
                torder.save()
                order[shop_id] = torder
            order_goods = models.OrderGoods()
            order_goods.detail = shop_cart.goods.detail
            order_goods.num = shop_cart.num
            order_goods.orderinfo = order[shop_id]
            order_goods.remarks = remarks[str(shop_cart.id)]
            order_goods.save()
            shop_cart.deleted = True
            shop_cart.save()
        return Response('ok')

    def update(self, request, *args, **kwargs):
        print(self.request.user)
        id = kwargs['pk']
        order = models.OrderInfo.objects.get(id=id)
        order.status = 2
        order.pay_time = timezone.now()
        order.save()
        return Response({'msg': '修改成功'})

    @staticmethod
    def orderhandle(ordergoods):
        result = []
        for ordergood in ordergoods.all():
            exsited = False
            for item in result:
                if ordergood.detail.shop_id == item['shop_id']:
                    item['goods'].append(OrderGoodsSerializer(ordergood).data)
                    exsited = True
                    break
            if not exsited:
                temp = {'shop_id': ordergood.detail.shop_id, 'shop_name': ordergood.detail.shop.title, 'goods': []}
                temp['goods'].append(OrderGoodsSerializer(ordergood).data)
                result.append(temp)
        return result


class OrderCardsSerializer(serializers.ModelSerializer):
    status_display = serializers.CharField(source='get_status_display')
    phone = serializers.SerializerMethodField()
    pay_time = serializers.SerializerMethodField()
    userid = serializers.SerializerMethodField()
    nickname = serializers.SerializerMethodField()

    class Meta:
        model = models.OrderInfo
        fields = ['id', 'order_sn', 'pay_time', 'status', 'status_display', 'total_amount', 'phone', 'userid',
                  'nickname']

    @staticmethod
    def get_phone(obj):
        return obj.user_id.phone

    @staticmethod
    def get_pay_time(obj):
        return str(obj.pay_time)[:19]

    @staticmethod
    def get_userid(obj):
        return obj.user_id.studentid

    @staticmethod
    def get_nickname(obj):
        return obj.user_id.nickname


class OrderManageView(ListModelMixin, UpdateModelMixin, GenericViewSet):
    queryset = models.OrderInfo.objects.all()
    serializer_class = OrderCardsSerializer

    def list(self, request, *args, **kwargs):
        shop_id = self.request.user.shop_id
        mode = request.query_params.get('type')
        today = datetime.datetime.now().date()
        # 订单处理显示的今日订单
        if mode == '1':
            queryset = models.OrderInfo.objects.filter(status__in=[2, 3, 4], pay_time__date=today).all().order_by(
                '-pay_time')
            print(queryset)
        else:
            queryset = models.OrderInfo.objects.filter(status__in=[5, 6], pay_time__date=today).all().order_by(
                '-pay_time')
        result = []
        for order in queryset:
            if shop_id in list(order.goods.values_list('shop_id', flat=True)):
                result.append(OrderCardsSerializer(order).data)
        print(result)
        return Response(result)

    def update(self, request, *args, **kwargs):
        print(request.data)
        order_id = kwargs['pk']
        data = request.data
        order = models.OrderInfo.objects.get(id=order_id)
        order.status = data['status']
        print('order', order.status)
        if data['status'] == 3:
            # 已接单
            order.receive_time = timezone.now()
        elif data['status'] == 4:
            order.cookok_time = timezone.now()
            self.sendmessage(order)
        elif data['status'] == 5:
            order.orderok_time = timezone.now()
        elif data['status'] == 6:
            order.cancel_time = timezone.now()
        order.save()
        return Response(OrderCardsSerializer(order).data)

    @staticmethod
    def sendmessage(order):
        print("取餐")
        user = order.user_id
        openid = user.openid
        result = TaskResult.objects.filter(task_name='eatfun_backend.celery.gettokentask').all().first()
        # print(result.result)
        access_token = result.result.strip('"')
        print(access_token)
        template_id = 'dAMgTtBSPqoXWNQChClQlxoQ1DdEVVv7hoasGVtzJsU'
        pickno = '1212'
        order_sn = order.order_sn
        position = order.shop.position
        goods = order.goods.all()
        goodsname = []
        for good in goods:
            goodsname.append(good.cover.name)
        goodsname = ','.join(goodsname)
        data = {
            "thing1": {
                'value': '您的菜品已做好,请及时取餐'
            },
            'thing16': {
                'value': goodsname
            },
            'character_string17': {
                'value': pickno
            },
            'thing9': {
                'value': position
            },
            'character_string10': {
                'value': order_sn
            }
        }
        payload = {
            'touser': openid,
            'template_id': template_id,
            'page': 'order',
            'lang': 'zh_CN',
            'data': data
        }
        result = requests.post(f'https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token={access_token}',
                               json=payload)
        print(result.json())


class OrderQueryView(ListModelMixin, GenericViewSet):
    queryset = models.OrderInfo.objects.all()
    serializer_class = OrderCardsSerializer

    def list(self, request, *args, **kwargs):
        print(models.OrderInfo.objects.filter(status=0))
        shop_id = self.request.user.shop_id
        print(shop_id)
        status = request.query_params.get('status')
        print('status', status)
        date = request.query_params.get('date')
        print(date)
        # date = '2021-03-30'
        date = time.strptime(date, '%Y-%m-%d')
        y, m, d = date[0:3]
        date = datetime.datetime(y, m, d)
        if status != '0':
            queryset = models.OrderInfo.objects.filter(status=status, pay_time__date=date).all().order_by('-pay_time')
        else:
            print('sadasd')
            queryset = models.OrderInfo.objects.filter(pay_time__date=date).all().order_by('-pay_time')
        print(queryset)
        result = []
        for order in queryset:
            if shop_id in list(order.goods.values_list('shop_id', flat=True)):
                result.append(OrderCardsSerializer(order).data)
        return Response(result)


class Gettoken(APIView):
    authentication_classes = []

    def post(self, request, *args, **kwargs):
        result = TaskResult.objects.filter(task_name='eatfun_backend.celery.gettokentask').last()
        print(str(result.result))
        return Response("dsds")
